
/****************************************************************************/

int kernelMultitaskerGetProcessPriority(int processId)
{
	int status = 0;
	kernelProcess *getProcess;

	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	ACQUIRE_LOCK_PROCESS_QUEUE();

	getProcess = getProcessById(processId);

	if (getProcess == NULL)
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	// No permission check necessary here

	status = getProcess->priority;

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status);
}

/****************************************************************************/

int kernelMultitaskerSetProcessPriority(int processId, int newPriority)
{
	int status = 0;
	kernelProcess *changeProcess;

	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	// Make sure the new priority is a legal one
	if ((newPriority < 0) || (newPriority >= (PRIORITY_LEVELS)))
		return (status = ERR_INVALID);

	ACQUIRE_LOCK_PROCESS_QUEUE();

	changeProcess = getProcessById(processId);

	if (changeProcess == NULL)
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	// Permission check.  A privileged process can set the priority of any 
	// other process, but a non-privileged process can only change the 
	// priority of processes owned by the same user.  Additionally, a 
	// non-privileged process can only set the new priority to a value equal 
	// to or lower than its own priority.
	if (kernelCurrentProcess->privilege != PRIVILEGE_SUPERVISOR)
	{
		if ((kernelCurrentProcess->userId != changeProcess->userId) ||
		    (newPriority < kernelCurrentProcess->priority))
		{
			RELEASE_LOCK_PROCESS_QUEUE();
			return (status = ERR_PERMISSION);
		}
	}

	changeProcess->priority = newPriority;

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status);
}

/****************************************************************************/

static void setBoost(kernelProcess *targetProcess, int boostValue)
{
	if (boostValue > 0 && targetProcess->boost < boostValue * 3)
		targetProcess->boost = min(targetProcess->boost + boostValue, MAX_BOOST_VALUE);
	else if (boostValue < 0 && targetProcess->boost > boostValue * 3)
		targetProcess->boost = max(targetProcess->boost + boostValue, MIN_BOOST_VALUE);
}

/****************************************************************************/

int kernelMultitaskerSetProcessBoost(int processId, int boostValue)
{
	int status = 0;
	kernelProcess *changeProcess;

	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	if (boostValue < MIN_BOOST_VALUE)
		boostValue = MIN_BOOST_VALUE;
	else if (boostValue > MAX_BOOST_VALUE)
		boostValue = MAX_BOOST_VALUE;

	ACQUIRE_LOCK_PROCESS_QUEUE();

	changeProcess = getProcessById(processId);

	if (changeProcess == NULL)
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	// Permission check.  A privileged process can set the boost of any 
	// other process, but a non-privileged process can only change the 
	// boost of processes owned by the same user.
	if (kernelCurrentProcess->privilege != PRIVILEGE_SUPERVISOR)
	{
		if (kernelCurrentProcess->userId != changeProcess->userId)
		{
			RELEASE_LOCK_PROCESS_QUEUE();
			return (status = ERR_PERMISSION);
		}
	}

	setBoost(changeProcess, boostValue);

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status = 0);
}

/****************************************************************************/

